Skip to content

Add Tweedie distribution#2045

Open
nalimilan wants to merge 1 commit intomasterfrom
nl/tweedie
Open

Add Tweedie distribution#2045
nalimilan wants to merge 1 commit intomasterfrom
nl/tweedie

Conversation

@nalimilan
Copy link
Member

@nalimilan nalimilan commented Mar 16, 2026

This distribution is tricky to implement as there is no closed form for most functions. PDF is computed based on wrightbessel (JuliaMath/SpecialFunctions.jl#512). CDF and quantile are computed numerically from PDF. Performance is similar to reference R package tweedie.

When 1 < p < 2 it is continuous but with a point mass at zero so it is not completely correct to consider it a ContinuousUnivariateDistribution. When p = 1 it is even discrete. However I wasn't sure that justifies adding a new type like SemiContinuousUnivariateDistribution.

This distribution is useful to allow estimating Tweedie models in GLM.

This distribution is tricky to implement as there
is no closed form for most functions. PDF is computed
based on `wrightbessel`. CDF and quantile
are computed numerically. Performance is similar to
reference R package tweedie.

When `1 < p < 2` it is continuous but with a point
mass at zero so it is not completely correct to
consider it a `ContinuousUnivariateDistribution`. When
`p = 1` it is even discrete.
@devmotion
Copy link
Member

Tests fail currently.

Comment on lines +54 to +56
@check_args Tweedie (μ, μ >= zero(μ))
@check_args Tweedie (σ, σ >= zero(σ))
@check_args Tweedie (p, 1 <= p <= 2)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not 100% sure but IIRC you can use a single check_args with a Tuple of checks.

Comment on lines +63 to +64
Tweedie(μ::Integer, σ::Integer, p::Integer; check_args::Bool=true) =
Tweedie(float(μ), float(σ), float(p); check_args=check_args)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not needed?

Suggested change
Tweedie::Integer, σ::Integer, p::Integer; check_args::Bool=true) =
Tweedie(float(μ), float(σ), float(p); check_args=check_args)

Tweedie(float(μ), float(σ), float(p); check_args=check_args)

#### Conversions
convert(::Type{Tweedie{T}}, μ::S, σ::S, p::S) where {T <: Real, S <: Real} = Tweedie(T(μ), T(σ), T(p))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IMO no such method should be defined - users should use the constructor:

Suggested change
convert(::Type{Tweedie{T}}, μ::S, σ::S, p::S) where {T <: Real, S <: Real} = Tweedie(T(μ), T(σ), T(p))

#### Parameters

params(d::Tweedie) = (d.μ, d.σ, d.p)
partype(d::Tweedie{T}) where {T} = T
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
partype(d::Tweedie{T}) where {T} = T
partype(::Tweedie{T}) where {T} = T

#### Statistics

mean(d::Tweedie) = d.μ
var(d::Tweedie) = d.σ^2 * d.μ^d.p
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd suggest defining std as well to avoid unnecessary squaring and subsequent square root calculations:

Suggested change
var(d::Tweedie) = d.σ^2 * d.μ^d.p
var(d::Tweedie) = d.σ^2 * d.μ^d.p
std(d::Tweedle) = d.σ * d.μ^(d.p/2)

Comment on lines +5498 to +5506
"properties": {
"location": 2,
"scale": 1.5,
"shape": 1.01,
"mean": 2,
"var": 4.53129997525524,
"skewness": 1.07498594232179,
"kurtosis": 1.16703630862699
},
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
"properties": {
"location": 2,
"scale": 1.5,
"shape": 1.01,
"mean": 2,
"var": 4.53129997525524,
"skewness": 1.07498594232179,
"kurtosis": 1.16703630862699
},

Comment on lines +5531 to +5539
"properties": {
"location": 2,
"scale": 1.5,
"shape": 1.5,
"mean": 2,
"var": 6.36396103067893,
"skewness": 1.89201693432086,
"kurtosis": 4.7729707730092
},
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
"properties": {
"location": 2,
"scale": 1.5,
"shape": 1.5,
"mean": 2,
"var": 6.36396103067893,
"skewness": 1.89201693432086,
"kurtosis": 4.7729707730092
},

Comment on lines +5564 to +5572
"properties": {
"location": 2,
"scale": 1.5,
"shape": 1.99,
"mean": 2,
"var": 8.93783245893332,
"skewness": 2.97467268454119,
"kurtosis": 13.2507835119916
},
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
"properties": {
"location": 2,
"scale": 1.5,
"shape": 1.99,
"mean": 2,
"var": 8.93783245893332,
"skewness": 2.97467268454119,
"kurtosis": 13.2507835119916
},

Comment on lines +5597 to +5605
"properties": {
"location": 2,
"scale": 1.5,
"shape": 2,
"mean": 2,
"var": 9,
"skewness": 3,
"kurtosis": 13.5
},
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
"properties": {
"location": 2,
"scale": 1.5,
"shape": 2,
"mean": 2,
"var": 9,
"skewness": 3,
"kurtosis": 13.5
},

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should also test Float32 inputs, integer inputs and mixes of Float32, Float64, and integers, and add @inferred around the function calls. This would have caught the type stability issues.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants